package com.example.opengltest1;

import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.util.Log;

import java.nio.ByteBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

public class GLFrameRenderer implements GLSurfaceView.Renderer {
    private final String tag = "test_GLES_renderer";

    private GLSurfaceView mTargetSurface;
    private GLProgram mProgram = new GLProgram();
    private int mWidth = -1, mHeight = -1;
    private ByteBuffer y, u, v;

    public GLFrameRenderer(GLSurfaceView surface) {
        mTargetSurface = surface;
    }

    /*******************
     * 当Renderer对应的GLSurfaceView被创建时执行
     * **************/
    @Override
    public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
        // 设置清零背景色
        GLES20.glClearColor(0.0f,0.0f,0.0f, 1.0f);
        if (!mProgram.isProgramBuild()) {
            mProgram.buildProgram();
        }
    }

    /******************
     * 当Renderer对应的GLSurfaceView容器改变时执行
     * *************/
    @Override
    public void onSurfaceChanged(GL10 gl10, int i, int i1) {
//        Log.d(tag, "a : " + i + " b : " + i1);    i = 1080; i1 = 1920
        // 设置渲染器的绘制窗口，前两个参数是窗口顶点坐标，后两个是宽高
        GLES20.glViewport(i/6, i1/6, i/2, i1/2);
    }

    /***************
     * Renderer模式：连续渲染（每隔一段时间自动执行）、按需渲染（用户调用请求后执行）
     * *****************/
    @Override
    public void onDrawFrame(GL10 gl10) {
        // 获取对象锁
        synchronized (this) {
            if (y != null) {
                y.position(0);
                u.position(0);
                v.position(0);
                mProgram.buildTextures(y, u, v, mWidth, mHeight);
                GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
                mProgram.drawFrame();
            }
        }
    }

    /**************
     * 获取图像宽高，预先分配渲染数据内存
     * *****************/
    public void update(int w, int h) {
        if (w > 0 && h > 0) {
            if (w != mWidth && h != mHeight) {
                this.mWidth = w;
                this.mHeight = h;
                int yarraySize = w * h;
                int uvarraySize = yarraySize / 4;
                // 获取对象锁
                synchronized (this) {
                    y = ByteBuffer.allocate(yarraySize);
                    u = ByteBuffer.allocate(uvarraySize);
                    v = ByteBuffer.allocate(uvarraySize);
                }
            }
        }
    }

    /************
     * 传入或更新渲染数据
     * **************/
    public void update(byte[] ydata, byte[] udata, byte[] vdata) {
        // 获取对象锁
        synchronized (this) {
            y.clear();
            u.clear();
            v.clear();
            y.put(ydata, 0, ydata.length);
            u.put(udata, 0, udata.length);
            v.put(vdata, 0, vdata.length);
        }

        mTargetSurface.requestRender();
    }
}
